#include "HttpTurnnel.h"
#include <iostream>

using namespace std;

CHttpTurnnel::CHttpTurnnel(SOCKET sSock) :mStage(eTurnnelIniting)
{
	mSide1Socket = new CTCPSocket(sSock, Side1MsgHandle, this);
}


CHttpTurnnel::~CHttpTurnnel()
{/*
	if (mThread) {
		mThread->detach();
		mThread = NULL;
	}*/
}

BOOL CHttpTurnnel::InitTurnnel()
{
	return mSide1Socket->Start();
}


int CHttpTurnnel::ConnectServer(char*buf, long buflen)
{
	string msg(buf);
	BOOL relay = FALSE;
	string host, port;
	string line1 = msg.substr(0, msg.find("\r\n"));
	int pos = line1.find(" ");
	if (pos == string::npos)
		return -1;
	string method = msg.substr(0, pos);
	if (method == "CONNECT") {
		int pos2 = line1.find(":");
		if (pos2 == string::npos)
			return -2;
		host = line1.substr(pos + 1, pos2 - pos - 1);
		port = line1.substr(pos2 + 1, line1.length() - pos2 - 1);
	}
	else {
		//doing later here
		int pos2 = msg.find("Host: ");
		if (pos2 == string::npos) {
			return -2;
		}
		host = msg.substr(pos2 + 6, msg.length() - pos2 - 6);
		pos2 = host.find("\r\n");
		if (pos2 == string::npos) {
			return -2;
		}
		host = host.substr(0, pos2);
		if (host == "www.baidu.com") {
			int a=1;
		}
		port = "80";
		relay = TRUE;
	}
	hostent * record = gethostbyname(host.c_str());
	if (record == NULL) {
		return -4;
	}

	in_addr * address = (in_addr *)record->h_addr;
	string ip_address = inet_ntoa(*address);

	mSide2Socket = new CTCPSocket(Side2MsgHandle, this, ip_address, atoi(port.c_str()));
	if (!mSide2Socket) {
		return -5;
	}

	if (mSide2Socket->Start() == FALSE)
		return -6;

	if (relay) {
		mSide2Socket->Write(buf, buflen);
		return 1;
	}
	return 0;
}

int CHttpTurnnel::Side1MsgHandle(char*buf, long buflen, LPVOID argv)
{
	CHttpTurnnel*mThis = reinterpret_cast<CHttpTurnnel*>(argv);
#define SUCCESSMSG "HTTP/1.1 200 Connection established\r\n\r\n"
	int ret = 0;
	switch (mThis->mStage)
	{
	case eTurnnelIniting:
	{
		ret = mThis->ConnectServer(buf, buflen);
		if (ret < 0) {
			//Failed
			mThis->mSide1Socket->Write("", 0);
			return ret;
		}
		mThis->mStage = eTurnnelInited;
		if (ret == 0)
			ret = mThis->mSide1Socket->Write(SUCCESSMSG, strlen(SUCCESSMSG));
		break;
	}
	default: {
		ret = mThis->mSide2Socket->Write(buf, buflen);
		break;
	}
	}
	return ret;
}

int CHttpTurnnel::Side2MsgHandle(char*buf, long buflen, LPVOID argv)
{
	CHttpTurnnel*mThis = reinterpret_cast<CHttpTurnnel*>(argv);

	return mThis->mSide1Socket->Write(buf, buflen);
}
